using Devil;
using GameToolkit.UI;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

namespace GameToolkit.Editor
{
    [CustomEditor(typeof(EmojiAnims))]
    public class EmojiAnimsEditor : UnityEditor.Editor
    {
        readonly string numPattern = @"^\d+$";

        SerializedProperty m_Anims;
        ReorderableList mDropList;
        int mDropIndex = -1;
        float mDuration;
        SerializedProperty mDropAnim;


        GUIContent mImgIcon;
        GUIContent mRotateIcon;

        public static string FormatTime(float seconds)
        {
            string s = "[{0:00}:{1:00.000}]";
            int sec = Mathf.FloorToInt(seconds);
            seconds -= sec;
            int minute = sec / 60;
            //sec = sec % 60;
            //int hour = minute / 60;
            //minute = minute % 60;

            return string.Format(s, minute, seconds);
        }

        private void OnEnable()
        {
            m_Anims = serializedObject.FindProperty("m_Anims");
            SetDropIndex(-1, null, true);
            mImgIcon = new GUIContent(EditorGUIUtility.IconContent("PreTextureRGB"));
            mImgIcon.tooltip = "Sprite's name or frame's index";
            mRotateIcon = new GUIContent(EditorGUIUtility.IconContent("RotateTool"));
            mRotateIcon.tooltip = "Rotate angles";
        }

        void SetDropIndex(int index, SerializedProperty property, bool forceReset = false)
        {
            if (mDropIndex == index && !forceReset)
                return;
            mDropIndex = index;
            if (index != -1)
            {
                mDropAnim = property;
                mDropList = new ReorderableList(serializedObject, property.FindPropertyRelative("m_Frames"), true, true, true, true);
                mDropList.drawElementCallback = DrawFrameElement;
                mDropList.drawHeaderCallback = DrawFramesTitle;
                mDropList.onAddCallback = AddFrame;
            }
        }

        private void AddFrame(ReorderableList list)
        {
            var n = -1;
            if (list.index >= 0 && list.index < list.count)
            {
                n = list.index + 1;
                list.serializedProperty.InsertArrayElementAtIndex(n);
            }
            else
            {
                n = list.serializedProperty.arraySize;
                list.serializedProperty.arraySize++;
            }
            var p = list.serializedProperty.GetArrayElementAtIndex(n);
            p.FindPropertyRelative("m_Sprite").stringValue = "";
            p.FindPropertyRelative("index").intValue = 0;
            p.FindPropertyRelative("m_Rotate").floatValue = 0;
            list.index = n;
            GUI.changed = true;
            //serializedObject.ApplyModifiedProperties();
        }

        private void DrawFramesTitle(Rect rect)
        {
            EditorGUI.LabelField(rect, "Frames");
        }

        private void DrawFrameElement(Rect rect, int index, bool isActive, bool isFocused)
        {
            var area = new Rect(rect.x, rect.y, 80, rect.height);
            EditorGUI.LabelField(area, FormatTime(mDuration * index));

            var property = mDropList.serializedProperty.GetArrayElementAtIndex(index);
            var pname = property.FindPropertyRelative("m_Sprite");
            area = new Rect(rect.x + 80, rect.center.y - 10, 20, 20);
            EditorGUI.LabelField(area, mImgIcon);
            // spr
            area = new Rect(rect.x + 100, rect.y + 1, rect.width - 180, rect.height - 4);
            var str = DevilEditorUtility.TextField(area, pname.stringValue, "Sprite's name or Frame's index");
            if (str != pname.stringValue)
            {
                pname.stringValue = str;
                GUI.changed = true;
                if (Regex.IsMatch(str, numPattern))
                {
                    var num = int.Parse(str);
                    var v = property.FindPropertyRelative("index");
                    GUI.changed |= num != v.intValue;
                    v.intValue = num;
                }
            }
            area = new Rect(rect.xMax - 80, rect.center.y - 10, 20, 20);
            EditorGUI.LabelField(area, mRotateIcon);
            area = new Rect(rect.xMax - 60, rect.y + 1, 60, 17);
            var rot = property.FindPropertyRelative("m_Rotate");
            DevilEditorUtility.FloatField(area, rot);
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            var dirty = false;
            var tar = (EmojiAnims)target;
            EditorGUI.BeginChangeCheck();
            for (int i = 0; i < m_Anims.arraySize; i++)
            {
                var emoji = tar.m_Anims[i];
                var p = m_Anims.GetArrayElementAtIndex(i);
                var drop = mDropIndex == i;
                var rect = QuickGUI.BeginGroupRect(emoji.m_Name.name, 17, ref drop);
                var del = GUI.Button(new Rect(rect.xMax - 16, rect.y, 15, 15), DevilEditorUtility.EmptyContent, "OL Minus");
                if (drop)
                {
                    SetDropIndex(i, p);
                }
                else if (mDropIndex == i)
                {
                    SetDropIndex(-1, null);
                }
                if (drop)
                {
                    var aname = p.FindPropertyRelative("m_Name");
                    // var drop = QuickGUI.BeginGroup(p.displayName, mDropIndex == i);
                    EditorGUILayout.PropertyField(aname);
                    var duration = p.FindPropertyRelative("m_Duration");
                    mDuration = duration.floatValue;
                    EditorGUILayout.PropertyField(duration);
                    mDropList.DoLayoutList();

                    if (mDropList.index >= 0 && mDropList.index < mDropList.count && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Delete)
                    {
                        Event.current.Use();
                        mDropList.serializedProperty.DeleteArrayElementAtIndex(mDropList.index);
                        GUI.changed = true;
                    }
                }
                QuickGUI.EndGroup();
                if (del)
                {
                    dirty = true;
                    m_Anims.DeleteArrayElementAtIndex(i);
                    if (drop)
                        SetDropIndex(-1, null);
                }
            }
            EditorGUILayout.BeginVertical("U2D.createRect");
            if (QuickGUI.TitleBar("New Emoji Animation", 13) == 0)
            {
                dirty = true;
                m_Anims.arraySize++;
                var p = m_Anims.GetArrayElementAtIndex(m_Anims.arraySize - 1);
                p.FindPropertyRelative("m_Name.name").stringValue = "new emoji";
                p.FindPropertyRelative("m_Name.id").intValue = ParallelUtils.IgnoreCaseToHash("new emoji");
                p.FindPropertyRelative("m_Frames").arraySize = 0;
                //InsertAnim(mTarget.m_Anims == null ? 0 : mTarget.m_Anims.Length);
                //mDropIndex = mTarget.m_Anims.Length - 1;
                GUI.FocusControl(null);
                SetDropIndex(m_Anims.arraySize - 1, p);
            }
            EditorGUILayout.EndVertical();
            dirty |= EditorGUI.EndChangeCheck();
            if (dirty)
                serializedObject.ApplyModifiedProperties();
        }
    }
}